home *** CD-ROM | disk | FTP | other *** search
/ PC Answers 1995 May / PC Answers CD-ROM 7 (Future Publishing) (May 1995).iso / vbits / code / mee / vbdao / visdata / visdata.bas < prev    next >
Encoding:
BASIC Source File  |  1994-10-06  |  28.3 KB  |  1,097 lines

  1. '------------------------------------------------------------
  2. ' VISDATA.BAS
  3. ' support functions for the Visual Data sample application
  4. '
  5. ' General Information: This app is intended to demonstrate
  6. '   and exercise all of the functionality available in the
  7. '   VT (Virtual Table) Object layer in VB 3.0 Pro.
  8. '
  9. '   Any valid SQL statement may be sent via the Utility SQL
  10. '   function excluding "select" statements which may be
  11. '   executed from the Dynaset Create function. With these
  12. '   two features, this simple app becomes a powerful data
  13. '   definition and query tool accessing any ODBC driver
  14. '   available at the time.
  15. '
  16. '   The app has the capability to perform all DDL (data
  17. '   definition language) functions. These are accessed
  18. '   from the "Tables" form. This form accesses the
  19. '   "NewTable", "AddField" and "IndexAdd" forms to do
  20. '   the actual table, field and index definition.
  21. '   Tables and Indexes may be deleted when the corresponding
  22. '   "Delete" button is enabled. It is not possible to
  23. '   delete fields.
  24. '
  25. ' Naming Conventions:
  26. '   "f..."   = Form
  27. '   "c..."   = Form control
  28. '   "F..."   = Form level variable
  29. '   "gst..." = Global String
  30. '   "gf..."  = Global flag (true/false)
  31. '   "gw..."  = Global 2 byte integer value
  32. '
  33. '------------------------------------------------------------
  34.  
  35. Option Explicit
  36.  
  37. 'api declarations
  38. Declare Function OSGetPrivateProfileString% Lib "KERNEL" Alias "GetPrivateProfileString" (ByVal AppName$, ByVal KeyName$, ByVal keydefault$, ByVal ReturnString$, ByVal NumBytes As Integer, ByVal Filename$)
  39. Declare Function OSWritePrivateProfileString% Lib "KERNEL" Alias "WritePrivateProfileString" (ByVal AppName$, ByVal KeyName$, ByVal keydefault$, ByVal Filename$)
  40. Declare Function OSGetWindowsDirectory% Lib "KERNEL" Alias "GetWindowsDirectory" (ByVal a$, ByVal b%)
  41. Declare Function TimeGetTime& Lib "MMSYSTEM.DLL" ()
  42.  
  43. 'ODBC.DLL APIs
  44. Declare Function SQLDataSources Lib "ODBC.DLL" (ByVal henv As Long, ByVal fdir As Integer, ByVal szDSN As String, ByVal cbDSNMAx As Integer, pcbDSN As Integer, ByVal szDesc As String, ByVal cbDescMax As Integer, pcbDesc As Integer) As Integer
  45. Declare Function SQLAllocEnv Lib "ODBC.DLL" (env As Long) As Integer
  46.  
  47. 'global object variables
  48. Global gCurrentDB As Database
  49. Global gfDBOpenFlag As Integer
  50. Global gCurrentDS As Dynaset
  51. Global gCurrentTbl As Table
  52. Global gCurrentQueryDef As QueryDef
  53. Global gCurrentField As Field
  54. Global gCurrentIndex As Index
  55. Global gTableListSS As Snapshot
  56.  
  57. 'global database variables
  58. Global gstDataType As String
  59. Global gstDBName As String
  60. Global gstUserName As String
  61. Global gstPassword As String
  62. Global gstDataBase As String
  63. Global gstDynaString As String
  64. Global gstTblName As String
  65. Global glQueryTimeout As Long
  66. Global glLoginTimeout As Long
  67. Global gstTableDynaFilter As String
  68.  
  69. 'other global vars
  70. Global gstZoomData As String
  71. Global gwMaxGridRows As Long
  72.  
  73. 'new field properties
  74. Global gwFldType As Integer
  75. Global gwFldSize As Integer
  76.  
  77. 'global find values
  78. Global gfFindFailed As Integer
  79. Global gstFindExpr As String
  80. Global gstFindOp As String
  81. Global gstFindField As String
  82. Global gfFindMatch As Integer
  83. Global gfFromTableView As Integer
  84.  
  85. 'global seek values
  86. Global gstSeekOperator As String
  87. Global gstSeekValue As String
  88.  
  89. 'global flags
  90. Global gfDBChanged As Integer
  91. Global gfFromSQL As Integer
  92. Global gfTransPending As Integer
  93. Global gfAddTableFlag As Integer
  94.  
  95. 'data backend types
  96. Global Const MSACCESS = "MS Access"
  97. Global Const DBASEIII = "dBASE III"
  98. Global Const dBASEIV = "dBASE IV"
  99. Global Const FOXPRO20 = "FoxPro 2.0"
  100. Global Const FOXPRO25 = "FoxPro 2.5"
  101. Global Const PARADOX = "Paradox 3.X"
  102. Global Const BTRIEVE = "Btrieve"
  103. Global Const SQLDB = "ODBC"
  104.  
  105. 'global constants
  106. Global Const DEFAULTDRIVER = "SQL Server"
  107. Global Const MODAL = 1
  108. Global Const HOURGLASS = 11
  109. Global Const DEFAULT_MOUSE = 0
  110. Global Const YES = 6
  111. Global Const MSGBOX_TYPE = 4 + 48 + 256
  112. Global Const TRUE_ST = "True"
  113. Global Const FALSE_ST = "False"
  114. Global Const EOF_ERR = 626
  115. Global Const FTBLS = 0
  116. Global Const FFLDS = 1
  117. Global Const FINDX = 2
  118. Global Const MAX_GRID_ROWS = 31999
  119. Global Const MAX_MEMO_SIZE = 20000
  120. Global Const GETCHUNK_CUTOFF = 50
  121. Global Const NULL_STR = ""
  122. Global CRLF As String
  123.  
  124.  
  125. 'field type constants
  126. Global Const FT_TRUEFALSE = 1
  127. Global Const FT_BYTE = 2
  128. Global Const FT_INTEGER = 3
  129. Global Const FT_LONG = 4
  130. Global Const FT_CURRENCY = 5
  131. Global Const FT_SINGLE = 6
  132. Global Const FT_DOUBLE = 7
  133. Global Const FT_DATETIME = 8
  134. Global Const FT_STRING = 10
  135. Global Const FT_BINARY = 11
  136. Global Const FT_MEMO = 12
  137.  
  138. 'table type constants
  139. Global Const DB_TABLE = 1
  140. Global Const DB_ATTACHEDTABLE = 6
  141. Global Const DB_ATTACHEDODBC = 4
  142. Global Const DB_QUERYDEF = 5
  143. Global Const DB_SYSTEMOBJECT = &H80000002
  144.  
  145. 'dynaset option parameter constants
  146. Global Const VBDA_DENYWRITE = &H1
  147. Global Const VBDA_DENYREAD = &H2
  148. Global Const VBDA_READONLY = &H4
  149. Global Const VBDA_APPENDONLY = &H8
  150. Global Const VBDA_INCONSISTENT = &H10
  151. Global Const VBDA_CONSISTENT = &H20
  152. Global Const VBDA_SQLPASSTHROUGH = &H40
  153.  
  154. 'db create/compact constants
  155. Global Const DB_CREATE_GENERAL = ";langid=0x0809;cp=1252;country=0"
  156. Global Const DB_VERSION10 = 1
  157.  
  158. ' Microsoft Access QueryDef types
  159. Global Const DB_QACTION = &HF0
  160. Global Const DB_QCROSSTAB = &H10
  161. Global Const DB_QDELETE = &H20
  162. Global Const DB_QUPDATE = &H30
  163. Global Const DB_QAPPEND = &H40
  164. Global Const DB_QMAKETABLE = &H50
  165.  
  166. ' Index Attributes
  167. Global Const DB_UNIQUE = 1
  168. Global Const DB_PRIMARY = 2
  169. Global Const DB_PROHIBITNULL = 4
  170. Global Const DB_IGNORENULL = 8
  171. Global Const DB_DESCENDING = 1  'For each field in Index
  172.  
  173. Function ActionQueryType (qn As String) As String
  174.   Dim i As Integer
  175.  
  176.   gTableListSS.MoveFirst
  177.   While gTableListSS.EOF = False And gTableListSS!Name <> qn
  178.     gTableListSS.MoveNext
  179.   Wend
  180.   If gTableListSS!Name = qn Then
  181.     Select Case gTableListSS!Attributes
  182.       Case DB_QCROSSTAB
  183.         ActionQueryType = "Cross Tab"
  184.       Case DB_QDELETE
  185.         ActionQueryType = "Delete"
  186.       Case DB_QUPDATE
  187.         ActionQueryType = "Update"
  188.       Case DB_QAPPEND
  189.         ActionQueryType = "Append"
  190.       Case DB_QMAKETABLE
  191.         ActionQueryType = "Make Table"
  192.     End Select
  193.   Else
  194.     ActionQueryType = NULL_STR
  195.   End If
  196.  
  197. End Function
  198.  
  199. Function AddBrackets (objname As String) As String
  200.   'add brackets to object names w/ spaces in them
  201.   If InStr(objname, " ") > 0 And Mid(objname, 1, 1) <> "[" Then
  202.     AddBrackets = "[" & objname & "]"
  203.   Else
  204.     AddBrackets = objname
  205.   End If
  206. End Function
  207.  
  208. Function ASCIItoBM (bm As String)
  209.   Dim i As Integer
  210.   Dim ret As String, tmp As String
  211.  
  212.   For i = 1 To Len(bm)
  213.     If Mid(bm, i, 1) = "," Then
  214.       ret = ret + Chr(CInt(tmp))
  215.       tmp = NULL_STR
  216.     Else
  217.       tmp = tmp + Mid(bm, i, 1)
  218.     End If
  219.   Next
  220.  
  221.   ASCIItoBM = ret
  222.  
  223. End Function
  224.  
  225. Function BMtoASCII (bm As String)
  226.   Dim i As Integer
  227.   Dim ret As String
  228.  
  229.   For i = 1 To Len(bm)
  230.     ret = ret + CStr(Asc(Mid(bm, i, 1))) & ","
  231.   Next
  232.  
  233.   BMtoASCII = ret
  234. End Function
  235.  
  236. Function CheckTransPending (msg As String) As Integer
  237.  
  238.   If gfTransPending = True Then
  239.     MsgBox msg & CRLF & "Execute Commit or Rollback First.", 48
  240.     CheckTransPending = True
  241.   Else
  242.     CheckTransPending = False
  243.   End If
  244.  
  245. End Function
  246.  
  247. Sub CloseAllDynasets ()
  248.   Dim i As Integer
  249.  
  250.   MsgBar "Closing Dynasets", True
  251.   While i < Forms.Count
  252.     If Forms(i).Tag = "Dynaset" Then
  253.       Unload Forms(i)
  254.     Else
  255.       i = i + 1
  256.     End If
  257.   Wend
  258.   MsgBar NULL_STR, False
  259.  
  260. End Sub
  261.  
  262. Function CopyData (from_db As Database, to_db As Database, from_nm As String, to_nm As String) As Integer
  263.   On Error GoTo CopyErr
  264.  
  265.   Dim ds1 As Dynaset, ds2 As Dynaset
  266.   Dim i As Integer, rc As Long, x As Long
  267.  
  268.   Set ds1 = from_db.CreateDynaset(from_nm)
  269.   Set ds2 = to_db.CreateDynaset(to_nm)
  270.  
  271.   While ds1.EOF = False
  272.     ds2.AddNew
  273.     For i = 0 To ds1.Fields.Count - 1
  274.       ds2(i) = ds1(i)
  275.     Next
  276.     ds2.Update
  277.     ds1.MoveNext
  278.     'if the to_db is an ODBC database, try to dump the trans logs
  279.     If InStr(to_db.Connect, "ODBC;") > 0 Then
  280.       rc = rc + 1
  281.       If rc Mod 1000 = 0 Then
  282.         On Error Resume Next
  283.         Debug.Print rc
  284.         Beep
  285.         x = to_db.ExecuteSQL("dump tran tcat with no_log")
  286.         On Error GoTo CopyErr
  287.       End If
  288.     End If
  289.   Wend
  290.  
  291.   CopyData = True
  292.   GoTo CopyEnd
  293.  
  294. CopyErr:
  295.   ShowError
  296.   CopyData = False
  297.   Resume CopyEnd
  298.  
  299. CopyEnd:
  300.  
  301. End Function
  302.  
  303. Function CopyStruct (from_db As Database, to_db As Database, from_nm As String, to_nm As String, create_ind As Integer) As Integer
  304.   On Error GoTo CSErr
  305.  
  306.   Dim i As Integer
  307.   Dim tbl As New TableDef    'table object
  308.   Dim fld As Field           'field object
  309.   Dim ind As Index           'index object
  310.  
  311.   'search to see if table exists
  312. namesearch:
  313.   For i = 0 To to_db.TableDefs.Count - 1
  314.     If UCase(to_db.TableDefs(i).Name) = UCase(to_nm) Then
  315.       If MsgBox(to_nm & " already exists, delete it?", 4) = YES Then
  316.          to_db.TableDefs.Delete to_db.TableDefs(to_nm)
  317.       Else
  318.          to_nm = InputBox("Enter New Table Name:")
  319.          If Len(to_nm) = 0 Then
  320.            Exit Function
  321.          Else
  322.            GoTo namesearch
  323.          End If
  324.       End If
  325.       Exit For
  326.     End If
  327.   Next
  328.  
  329.   'strip off owner if needed
  330.   tbl.Name = StripOwner(to_nm)
  331.  
  332.   'create the fields
  333.   For i = 0 To from_db.TableDefs(from_nm).Fields.Count - 1
  334.     Set fld = New Field
  335.     fld.Name = from_db.TableDefs(from_nm).Fields(i).Name
  336.     fld.Type = from_db.TableDefs(from_nm).Fields(i).Type
  337.     fld.Size = from_db.TableDefs(from_nm).Fields(i).Size
  338.     fld.Attributes = from_db.TableDefs(from_nm).Fields(i).Attributes
  339.     tbl.Fields.Append fld
  340.   Next
  341.  
  342.   'create the indexes
  343.   If create_ind <> False Then
  344.     For i = 0 To from_db.TableDefs(from_nm).Indexes.Count - 1
  345.       Set ind = New Index
  346.       ind.Name = from_db.TableDefs(from_nm).Indexes(i).Name
  347.       ind.Fields = from_db.TableDefs(from_nm).Indexes(i).Fields
  348.       ind.Unique = from_db.TableDefs(from_nm).Indexes(i).Unique
  349.       If gstDataType <> SQLDB Then
  350.         ind.Primary = from_db.TableDefs(from_nm).Indexes(i).Primary
  351.       End If
  352.       tbl.Indexes.Append ind
  353.     Next
  354.   End If
  355.  
  356.   'append the new table
  357.   to_db.TableDefs.Append tbl
  358.  
  359.   CopyStruct = True
  360.   GoTo CSEnd
  361.  
  362. CSErr:
  363.   ShowError
  364.   CopyStruct = False
  365.   Resume CSEnd
  366.  
  367. CSEnd:
  368.  
  369. End Function
  370.  
  371. 'sub used to create a sample table and fill it
  372. 'with NumbRecs number of rows
  373. 'can only be called from the debug window
  374. 'for example:
  375. 'CreateSampleTable "mytbl",100
  376. Sub CreateSampleTable (TblName As String, NumbRecs As Long)
  377.   Dim ds As Dynaset
  378.   Dim ii As Long
  379.   Dim t1 As New TableDef
  380.   Dim f1 As New Field
  381.   Dim f2 As New Field
  382.   Dim f3 As New Field
  383.   Dim f4 As New Field
  384.   Dim i1 As New Index
  385.   Dim i2 As New Index
  386.  
  387.   'create the data holding table
  388.   t1.Name = TblName
  389.   
  390.   f1.Name = "name"
  391.   f1.Type = FT_STRING
  392.   f1.Size = 25
  393.   t1.Fields.Append f1
  394.  
  395.   f2.Name = "address"
  396.   f2.Type = FT_STRING
  397.   f2.Size = 25
  398.   t1.Fields.Append f2
  399.  
  400.   f3.Name = "record"
  401.   f3.Type = FT_STRING
  402.   f3.Size = 10
  403.   t1.Fields.Append f3
  404.  
  405.   f4.Name = "id"
  406.   f4.Type = FT_LONG
  407.   f4.Size = 4
  408.   t1.Fields.Append f4
  409.  
  410.   gCurrentDB.TableDefs.Append t1
  411.  
  412.   'add the indexes
  413.   i1.Name = TblName & "1"
  414.   i1.Fields = "name"
  415.   i1.Unique = False
  416.   gCurrentDB.TableDefs(TblName).Indexes.Append i1
  417.  
  418.   i2.Name = TblName & "2"
  419.   i2.Fields = "id"
  420.   i2.Unique = True
  421.   gCurrentDB.TableDefs(TblName).Indexes.Append i2
  422.  
  423.   'add records to the table in reverse order
  424.   'so indexes have some work to do
  425.   Set ds = gCurrentDB.CreateDynaset(TblName)
  426.   For ii = NumbRecs To 1 Step -1
  427.     ds.AddNew
  428.     ds(0) = "name" & CStr(ii)
  429.     ds(1) = "addr" & CStr(ii)
  430.     ds(2) = "rec" & CStr(ii)
  431.     ds(3) = ii
  432.     ds.Update
  433.   Next
  434.  
  435. End Sub
  436.  
  437. Function FilePath (fname As String)
  438.   Dim i As Integer
  439.   On Error Resume Next
  440.  
  441.   For i = Len(fname) To 1 Step -1
  442.     If Mid(fname, i, 1) = "\" Then Exit For
  443.   Next
  444.  
  445.   If i > 1 Then
  446.     FilePath = Left(fname, i)
  447.   Else
  448.     FilePath = ""
  449.   End If
  450.  
  451. End Function
  452.  
  453. Function GetFieldType (ft As String) As Integer
  454.   'return field length
  455.   If ft = "String" Then
  456.     GetFieldType = FT_STRING
  457.   Else
  458.     Select Case ft
  459.       Case "Counter"
  460.         GetFieldType = FT_LONG
  461.       Case "True/False"
  462.         GetFieldType = FT_TRUEFALSE
  463.       Case "Byte"
  464.         GetFieldType = FT_BYTE
  465.       Case "Integer"
  466.         GetFieldType = FT_INTEGER
  467.       Case "Long"
  468.         GetFieldType = FT_LONG
  469.       Case "Currency"
  470.         GetFieldType = FT_CURRENCY
  471.       Case "Single"
  472.         GetFieldType = FT_SINGLE
  473.       Case "Double"
  474.         GetFieldType = FT_DOUBLE
  475.       Case "Date/Time"
  476.         GetFieldType = FT_DATETIME
  477.       Case "Binary"
  478.         GetFieldType = FT_BINARY
  479.       Case "Memo"
  480.         GetFieldType = FT_MEMO
  481.     End Select
  482.   End If
  483.  
  484. End Function
  485.  
  486. Function GetFieldWidth (t As Integer)
  487.   'determines the form control width
  488.   'based on the field type
  489.   Select Case t
  490.     Case FT_TRUEFALSE
  491.       GetFieldWidth = 850
  492.     Case FT_BYTE
  493.       GetFieldWidth = 650
  494.     Case FT_INTEGER
  495.       GetFieldWidth = 900
  496.     Case FT_LONG
  497.       GetFieldWidth = 1100
  498.     Case FT_CURRENCY
  499.       GetFieldWidth = 1800
  500.     Case FT_SINGLE
  501.       GetFieldWidth = 1800
  502.     Case FT_DOUBLE
  503.       GetFieldWidth = 2200
  504.     Case FT_DATETIME
  505.       GetFieldWidth = 2000
  506.     Case FT_STRING
  507.       GetFieldWidth = 3250
  508.     Case FT_BINARY
  509.       GetFieldWidth = 3250
  510.     Case FT_MEMO
  511.       GetFieldWidth = 3250
  512.     Case Else
  513.       GetFieldWidth = 3250
  514.   End Select
  515.  
  516. End Function
  517.  
  518. Function GetINIString$ (ByVal szItem$, ByVal szDefault$)
  519.   Dim tmp As String
  520.   Dim x As Integer
  521.  
  522.   tmp = String$(2048, 32)
  523.   x = OSGetPrivateProfileString("VISDATA", szItem$, szDefault$, tmp, Len(tmp), "VISDATA.INI")
  524.  
  525.   GetINIString = Mid$(tmp, 1, x)
  526. End Function
  527.  
  528. Function GetNumbRecs (FDS As Dynaset) As Long
  529.   Dim ds As Dynaset
  530.  
  531.   On Error GoTo GNRErr
  532.  
  533.   MsgBar "Calculating Number of Rows in Dynaset", True
  534.  
  535.   Set ds = FDS.Clone()
  536.   If Not ds.EOF Then ds.MoveLast
  537.   GetNumbRecs = ds.RecordCount
  538.   ds.Close
  539.  
  540.   GoTo GNREnd
  541.  
  542. GNRErr:
  543.   'just return because row count is non critical
  544.   GetNumbRecs = -1
  545.   Resume GNREnd
  546.  
  547. GNREnd:
  548.  
  549. End Function
  550.  
  551. Function GetNumbRecsSS (FDS As Snapshot) As Long
  552.   Dim ds As Snapshot
  553.  
  554.   On Error GoTo GNRSSErr
  555.   MsgBar "Calculating Number of Rows in SnapShot", True
  556.  
  557.   Set ds = FDS.Clone()
  558.   If Not ds.EOF Then ds.MoveLast
  559.   GetNumbRecsSS = ds.RecordCount
  560.   ds.Close
  561.  
  562.   GoTo GNRSSEnd
  563.  
  564. GNRSSErr:
  565.   'just return because row count is non critical
  566.   GetNumbRecsSS = -1
  567.   Resume GNRSSEnd
  568.  
  569. GNRSSEnd:
  570.  
  571. End Function
  572.  
  573. Function GetNumbRecsTbl (tbl As Table) As Long
  574.   Dim tbl2 As Table
  575.  
  576.   On Error GoTo GNRTErr
  577.  
  578.   MsgBar "Calculating Number of Rows in Table", True
  579.   Set tbl2 = tbl.Clone()
  580.   If Not tbl2.EOF Then tbl2.MoveLast
  581.   GetNumbRecsTbl = tbl2.RecordCount
  582.   tbl2.Close
  583.  
  584.   GoTo GNRTEnd
  585.  
  586. GNRTErr:
  587.   'just return because row count is non critical
  588.   GetNumbRecsTbl = -1
  589.   Resume GNRTEnd
  590.  
  591. GNRTEnd:
  592.  
  593. End Function
  594.  
  595. Function LoadGrid (grd As Control, FDS As Dynaset, dynst$, numb&, Start&) As Integer
  596.    Dim ft As Integer               'field type
  597.    Dim i As Integer, j As Integer  'for loop indexes
  598.    Dim fn As String                'field name
  599.    Dim rc As Integer               'record count
  600.    Dim gs As String                'grid string
  601.  
  602.    On Error GoTo LGErr
  603.  
  604.    MsgBar "Loading Grid for Table View", True
  605.    'setup the grid
  606.    grd.Rows = 2       'reduce the grid
  607.    grd.FixedRows = 0  'allow next step
  608.    grd.Rows = 1       'clears the grid completely
  609.    If FDS.Bookmarkable Then
  610.      grd.Cols = FDS.Fields.Count + 2
  611.    Else
  612.      grd.Cols = FDS.Fields.Count + 1
  613.    End If
  614.  
  615.    If Start& = 0 Then        'only do it on first call
  616.      On Error Resume Next
  617.      'set the column widths
  618.      For i = 0 To FDS.Fields.Count - 1
  619.        ft = FDS(i).Type
  620.        If ft = FT_STRING Then
  621.          If FDS(i).Size > Len(FDS(i).Name) Then
  622.            If FDS(i).Size <= 10 Then
  623.              grd.ColWidth(i + 1) = FDS(i).Size * fTables.TextWidth("A")
  624.            Else
  625.              grd.ColWidth(i + 1) = 10 * fTables.TextWidth("A")
  626.            End If
  627.          Else
  628.            If Len(FDS(i).Name) <= 10 Then
  629.              grd.ColWidth(i + 1) = Len(FDS(i).Name) * fTables.TextWidth("A")
  630.            Else
  631.              grd.ColWidth(i + 1) = 10 * fTables.TextWidth("A")
  632.            End If
  633.          End If
  634.        ElseIf ft = FT_MEMO Then
  635.          grd.ColWidth(i + 1) = 1200
  636.        Else
  637.          grd.ColWidth(i + 1) = GetFieldWidth(ft)
  638.        End If
  639.      Next
  640.  
  641.      On Error GoTo LGErr
  642.      'load the field names
  643.      grd.Row = 0
  644.      For i = 0 To FDS.Fields.Count - 1
  645.        grd.Col = i + 1
  646.        grd.Text = UCase(FDS(i).Name)
  647.      Next
  648.    End If
  649.  
  650.    rc = 1
  651.  
  652.    'fill method 1
  653.    'add the rows with the additem method
  654.    While FDS.EOF = False And rc <= numb
  655.      gs = CStr(rc + Start) + Chr$(9)
  656.      For i = 0 To FDS.Fields.Count - 1
  657.        If FDS(i).Type = FT_MEMO Then
  658.          If FDS(i).FieldSize() < 255 Then
  659.            gs = gs + StripNonAscii(vFieldVal(FDS(i))) + Chr$(9)
  660.          Else
  661.            'can only get the 1st 255 chars
  662.            gs = gs + StripNonAscii(vFieldVal(FDS(i).GetChunk(0, 255))) + Chr$(9)
  663.          End If
  664.        ElseIf FDS(i).Type = FT_STRING Then
  665.          gs = gs + StripNonAscii(vFieldVal(FDS(i))) + Chr$(9)
  666.        Else
  667.          gs = gs + vFieldVal(FDS(i)) + Chr$(9)
  668.        End If
  669.      Next
  670.      gs = Mid(gs, 1, Len(gs) - 1)
  671.      grd.AddItem gs
  672.      If FDS.Bookmarkable Then
  673.        grd.Row = grd.Rows - 1
  674.        grd.Col = grd.Cols - 1
  675.  
  676.        grd = BMtoASCII((FDS.Bookmark))
  677.  
  678.      End If
  679.      FDS.MoveNext
  680.      rc = rc + 1
  681.    Wend
  682.  
  683.    'fill method 2
  684.    'add the cells individually
  685. '   While fds.EOF = False And rc <= numb
  686. '     grd.Rows = rc + 1
  687. '     grd.Row = rc
  688. '     grd.Col = 0
  689. '     grd.Text = CStr(rc + start)
  690. '     For i = 0 To fds.Fields.Count - 1
  691. '       grd.Col = i + 1
  692. '       If fds(i).Type = FT_MEMO Then
  693. '         'can only get the 1st 255 chars
  694. '         grd.Text = StripNonAscii(vFieldVal((fds(i).GetChunk(0, 255))))
  695. '       ElseIf fds(i).Type = FT_STRING Then
  696. '         grd.Text = StripNonAscii(vFieldVal((fds(i))))
  697. '       Else
  698. '         grd.Text = CStr(vFieldVal(fds(i)))
  699. '       End If
  700. '     Next
  701. '     fds.MoveNext
  702. '     rc = rc + 1
  703. '   Wend
  704.  
  705.    grd.FixedRows = 1   'freeze the field names
  706.    grd.FixedCols = 1   'freeze the row numbers
  707.    grd.Row = 1         'set current position
  708.    grd.Col = 1
  709.    If FDS.Bookmarkable Then
  710.      grd.ColWidth(grd.Cols - 1) = 1
  711.    End If
  712.  
  713.    LoadGrid = rc       'return number added
  714.    GoTo LGEnd
  715.  
  716. LGErr:
  717.    ShowError
  718.    LoadGrid = False    'return 0
  719.    Resume LGEnd
  720.  
  721. LGEnd:
  722.    MsgBar NULL_STR, False
  723.  
  724. End Function
  725.  
  726. '----------------------------------------------------------------------------
  727. 'to use this function in any app,
  728. '1. create a form with a grid
  729. '2. create a dynaset
  730. '3. call this function from the form with
  731. '   grd    = your grid control name
  732. '   dynst$ = your dynaset open string (table name or SQL select statement)
  733. '   numb&  = the max number of rows to load (grid is limited to 2000)
  734. '   start& = starting row (needed to display the record number in the
  735. '            left column when loading blocks of records as the
  736. '            DynaGrid form in this app does with the "More" button)
  737. '----------------------------------------------------------------------------
  738. Function LoadGridSS (grd As Control, FDS As Snapshot, dynst$, numb&, Start&) As Integer
  739.    Dim ft As Integer               'field type
  740.    Dim i As Integer, j As Integer  'for loop indexes
  741.    Dim fn As String                'field name
  742.    Dim rc As Integer               'record count
  743.    Dim gs As String                'grid string
  744.  
  745.    On Error GoTo LGSSErr
  746.  
  747.    MsgBar "Loading Grid for Table View", True
  748.    'setup the grid
  749.    grd.Rows = 2       'reduce the grid
  750.    grd.FixedRows = 0  'allow next step
  751.    grd.Rows = 1       'clears the grid completely
  752.    If FDS.Bookmarkable Then
  753.      grd.Cols = FDS.Fields.Count + 2
  754.    Else
  755.      grd.Cols = FDS.Fields.Count + 1
  756.    End If
  757.  
  758.    If Start& = 0 Then        'only do it on first call
  759.      On Error Resume Next
  760.      'set the column widths
  761.      For i = 0 To FDS.Fields.Count - 1
  762.        ft = FDS(i).Type
  763.        If ft = FT_STRING Then
  764.          If FDS(i).Size > Len(FDS(i).Name) Then
  765.            If FDS(i).Size <= 10 Then
  766.              grd.ColWidth(i + 1) = FDS(i).Size * fTables.TextWidth("A")
  767.            Else
  768.              grd.ColWidth(i + 1) = 10 * fTables.TextWidth("A")
  769.            End If
  770.          Else
  771.            If Len(FDS(i).Name) <= 10 Then
  772.              grd.ColWidth(i + 1) = Len(FDS(i).Name) * fTables.TextWidth("A")
  773.            Else
  774.              grd.ColWidth(i + 1) = 10 * fTables.TextWidth("A")
  775.            End If
  776.          End If
  777.        ElseIf ft = FT_MEMO Then
  778.          grd.ColWidth(i + 1) = 1200
  779.        Else
  780.          grd.ColWidth(i + 1) = GetFieldWidth(ft)
  781.        End If
  782.      Next
  783.  
  784.      On Error GoTo LGSSErr
  785.      'load the field names
  786.      grd.Row = 0
  787.      For i = 0 To FDS.Fields.Count - 1
  788.        grd.Col = i + 1
  789.        grd.Text = UCase(FDS(i).Name)
  790.      Next
  791.    End If
  792.  
  793.    rc = 1
  794.  
  795.    'fill method 1
  796.    'add the rows with the additem method
  797.    While FDS.EOF = False And rc <= numb
  798.      gs = CStr(rc + Start) + Chr$(9)
  799.      For i = 0 To FDS.Fields.Count - 1
  800.        If FDS(i).Type = FT_MEMO Then
  801.          If FDS(i).FieldSize() < 255 Then
  802.            gs = gs + StripNonAscii(vFieldVal(FDS(i))) + Chr$(9)
  803.          Else
  804.            'can only get the 1st 255 chars
  805.            gs = gs + StripNonAscii(vFieldVal(FDS(i).GetChunk(0, 255))) + Chr$(9)
  806.          End If
  807.        ElseIf FDS(i).Type = FT_STRING Then
  808.          gs = gs + StripNonAscii(vFieldVal(FDS(i))) + Chr$(9)
  809.        Else
  810.          gs = gs + vFieldVal(FDS(i)) + Chr$(9)
  811.        End If
  812.      Next
  813.      gs = Mid(gs, 1, Len(gs) - 1)
  814.      grd.AddItem gs
  815.      If FDS.Bookmarkable Then
  816.        grd.Row = grd.Rows - 1
  817.        grd.Col = grd.Cols - 1
  818.  
  819.        grd = BMtoASCII((FDS.Bookmark))
  820.  
  821.      End If
  822.      FDS.MoveNext
  823.      rc = rc + 1
  824.    Wend
  825.  
  826.    'fill method 2
  827.    'add the cells individually
  828. '   While fds.EOF = False And rc <= numb
  829. '     grd.Rows = rc + 1
  830. '     grd.Row = rc
  831. '     grd.Col = 0
  832. '     grd.Text = CStr(rc + start)
  833. '     For i = 0 To fds.Fields.Count - 1
  834. '       grd.Col = i + 1
  835. '       If fds(i).Type = FT_MEMO Then
  836. '         'can only get the 1st 255 chars
  837. '         grd.Text = StripNonAscii(vFieldVal((fds(i).GetChunk(0, 255))))
  838. '       ElseIf fds(i).Type = FT_STRING Then
  839. '         grd.Text = StripNonAscii(vFieldVal((fds(i))))
  840. '       Else
  841. '         grd.Text = CStr(vFieldVal(fds(i)))
  842. '       End If
  843. '     Next
  844. '     fds.MoveNext
  845. '     rc = rc + 1
  846. '   Wend
  847.  
  848.    grd.FixedRows = 1   'freeze the field names
  849.    grd.FixedCols = 1   'freeze the row numbers
  850.    grd.Row = 1         'set current position
  851.    grd.Col = 1
  852.    If FDS.Bookmarkable Then
  853.      grd.ColWidth(grd.Cols - 1) = 1
  854.    End If
  855.  
  856.    LoadGridSS = rc       'return number added
  857.    GoTo LGSSEnd
  858.  
  859. LGSSErr:
  860.    ShowError
  861.    LoadGridSS = False    'return 0
  862.    Resume LGSSEnd
  863.  
  864. LGSSEnd:
  865.    MsgBar NULL_STR, False
  866.  
  867. End Function
  868.  
  869. Sub MsgBar (msg As String, pw As Integer)
  870.   If Len(msg) = 0 Then
  871.     VDMDI.cMsg = "Ready"
  872.   Else
  873.     If pw = True Then
  874.       VDMDI.cMsg = msg & ", please wait..."
  875.     Else
  876.       VDMDI.cMsg = msg
  877.     End If
  878.   End If
  879.   VDMDI.cMsg.Refresh
  880. End Sub
  881.  
  882. Sub RefreshTables (tbl_list As Control, IncludeQueries As Integer)
  883.    Dim i As Integer, j As Integer, h As Integer
  884.    Dim st As String
  885.    Dim OkayToAdd As Integer
  886.  
  887.    On Error GoTo TRefErr
  888.  
  889.    MsgBar "Refreshing Table List", True
  890.    SetHourglass VDMDI
  891.  
  892.    Set gTableListSS = gCurrentDB.ListTables()
  893.    tbl_list.Clear
  894.  
  895.    If IncludeQueries And gstDataType = MSACCESS Then
  896.      ' the ListTables method is used to display querydefs that might
  897.      ' be present in an Access database, see below for optional code
  898.      While gTableListSS.EOF = False
  899.        st = gTableListSS!Name
  900.        If VDMDI.PrefAllowSys.Checked = False Then
  901.          If (gTableListSS!Attributes And DB_SYSTEMOBJECT) = 0 Then
  902.            tbl_list.AddItem st
  903.          End If
  904.        Else
  905.          tbl_list.AddItem st
  906.        End If
  907.        gTableListSS.MoveNext
  908.      Wend
  909.    Else
  910.      ' this method uses the tabledefs collection but will not display
  911.      ' querydefs in an Access database
  912.      tbl_list.Clear
  913.      For i = 0 To gCurrentDB.TableDefs.Count - 1
  914.        st = gCurrentDB.TableDefs(i).Name
  915.        If VDMDI.PrefAllowSys.Checked = False Then
  916.          If (gCurrentDB.TableDefs(i).Attributes And DB_SYSTEMOBJECT) = 0 Then
  917.            tbl_list.AddItem st
  918.          End If
  919.        Else
  920.          tbl_list.AddItem st
  921.        End If
  922.      Next
  923.    End If
  924.   
  925.    GoTo TRefEnd
  926.  
  927. TRefErr:
  928.    ShowError
  929. '   gfDBOpenFlag = False
  930.    Resume TRefEnd
  931.  
  932. TRefEnd:
  933.    ResetMouse VDMDI
  934.    MsgBar NULL_STR, False
  935.  
  936. End Sub
  937.  
  938. Sub ResetMouse (f As Form)
  939.   VDMDI.MousePointer = DEFAULT_MOUSE
  940.   f.MousePointer = DEFAULT_MOUSE
  941. End Sub
  942.  
  943. Function SetFldProperties (ft As String) As String
  944.   'return field length
  945.   If ft = "String" Then
  946.     gwFldType = FT_STRING
  947.   Else
  948.     Select Case ft
  949.       Case "Counter"
  950.         SetFldProperties = "4"
  951.         gwFldType = FT_LONG
  952.         gwFldSize = 4
  953.       Case "True/False"
  954.         SetFldProperties = "1"
  955.         gwFldType = FT_TRUEFALSE
  956.         gwFldSize = 1
  957.       Case "Byte"
  958.         SetFldProperties = "1"
  959.         gwFldType = FT_BYTE
  960.         gwFldSize = 1
  961.       Case "Integer"
  962.         SetFldProperties = "2"
  963.         gwFldType = FT_INTEGER
  964.         gwFldSize = 2
  965.       Case "Long"
  966.         SetFldProperties = "4"
  967.         gwFldType = FT_LONG
  968.         gwFldSize = 4
  969.       Case "Currency"
  970.         SetFldProperties = "8"
  971.         gwFldType = FT_CURRENCY
  972.         gwFldSize = 8
  973.       Case "Single"
  974.         SetFldProperties = "4"
  975.         gwFldType = FT_SINGLE
  976.         gwFldSize = 4
  977.       Case "Double"
  978.         SetFldProperties = "8"
  979.         gwFldType = FT_DOUBLE
  980.         gwFldSize = 8
  981.       Case "Date/Time"
  982.         SetFldProperties = "8"
  983.         gwFldType = FT_DATETIME
  984.         gwFldSize = 8
  985.       Case "Binary"
  986.         SetFldProperties = "0"
  987.         gwFldType = FT_BINARY
  988.         gwFldSize = 0
  989.       Case "Memo"
  990.         SetFldProperties = "0"
  991.         gwFldType = FT_MEMO
  992.         gwFldSize = 0
  993.     End Select
  994.   End If
  995. End Function
  996.  
  997. Sub SetHourglass (f As Form)
  998.   DoEvents  'cause forms to repaint before going on
  999.   VDMDI.MousePointer = HOURGLASS
  1000.   f.MousePointer = HOURGLASS
  1001. End Sub
  1002.  
  1003. Sub ShowError ()
  1004.   Dim s As String
  1005.   
  1006.   s = "The following Error occurred:" & CRLF & CRLF
  1007.   'add the error string
  1008.   s = s + Error$ & CRLF
  1009.   'add the error number
  1010.   s = s & "Number: " & CStr(Err)
  1011.   'beep and show the error
  1012.   Beep
  1013.   MsgBox (s)
  1014.  
  1015. End Sub
  1016.  
  1017. Function StripBrackets (objname As String) As String
  1018.   'add brackets to object names w/ spaces in them
  1019.   If Mid(objname, 1, 1) = "[" Then
  1020.     StripBrackets = Mid(objname, 2, Len(objname) - 2)
  1021.   Else
  1022.     StripBrackets = objname
  1023.   End If
  1024.  
  1025. End Function
  1026.  
  1027. Function StripFileName (fname As String) As String
  1028.   On Error Resume Next
  1029.   Dim i As Integer
  1030.  
  1031.   For i = Len(fname) To 1 Step -1
  1032.     If Mid(fname, i, 1) = "\" Then
  1033.       Exit For
  1034.     End If
  1035.   Next
  1036.  
  1037.   StripFileName = Mid(fname, 1, i - 1)
  1038.  
  1039. End Function
  1040.  
  1041. Function StripNonAscii (vs As Variant) As String
  1042.   Dim i As Integer
  1043.   Dim ts As String
  1044.  
  1045.   For i = 1 To Len(vs)
  1046.     If Asc(Mid(vs, i, 1)) < 32 Or Asc(Mid(vs, i, 1)) > 126 Then
  1047.       ts = ts & " "
  1048.     Else
  1049.       ts = ts + Mid(vs, i, 1)
  1050.     End If
  1051.   Next
  1052.  
  1053.   StripNonAscii = ts
  1054.  
  1055. End Function
  1056.  
  1057. Function StripOwner (tblnm As String) As String
  1058.  
  1059.   If InStr(tblnm, ".") > 0 Then
  1060.     tblnm = Mid(tblnm, InStr(tblnm, ".") + 1, Len(tblnm))
  1061.   End If
  1062.   StripOwner = tblnm
  1063.  
  1064. End Function
  1065.  
  1066. Function stTrueFalse (tf As Variant) As String
  1067.   If tf = True Then
  1068.     stTrueFalse = "True"
  1069.   Else
  1070.     stTrueFalse = "False"
  1071.   End If
  1072. End Function
  1073.  
  1074. Function TableType (tbl As String) As Integer
  1075.   Dim i As Integer
  1076.  
  1077.   gTableListSS.MoveFirst
  1078.   While gTableListSS.EOF = False And gTableListSS!Name <> tbl
  1079.     gTableListSS.MoveNext
  1080.   Wend
  1081.   If gTableListSS!Name = tbl Then
  1082.     TableType = gTableListSS!TableType
  1083.   Else
  1084.     TableType = 0
  1085.   End If
  1086.  
  1087. End Function
  1088.  
  1089. Function vFieldVal (fval As Variant) As Variant
  1090.   If IsNull(fval) Then
  1091.     vFieldVal = NULL_STR
  1092.   Else
  1093.     vFieldVal = CStr(fval)
  1094.   End If
  1095. End Function
  1096.  
  1097.